/*
 * PUBLIC DOMAIN PCCTS-BASED C++ GRAMMAR (cplusplus.g, stat.g, expr.g)
 *
 * Authors: Sumana Srinivasan, NeXT Inc.;            sumana_srinivasan@next.com
 *          Terence Parr, Parr Research Corporation; parrt@parr-research.com
 *          Russell Quong, Purdue University;        quong@ecn.purdue.edu
 *
 * VERSION 1.2
 *
 * SOFTWARE RIGHTS
 *
 * This file is a part of the ANTLR-based C++ grammar and is free
 * software.  We do not reserve any LEGAL rights to its use or
 * distribution, but you may NOT claim ownership or authorship of this
 * grammar or support code.  An individual or company may otherwise do
 * whatever they wish with the grammar distributed herewith including the
 * incorporation of the grammar or the output generated by ANTLR into
 * commerical software.  You may redistribute in source or binary form
 * without payment of royalties to us as long as this header remains
 * in all source distributions.
 *
 * We encourage users to develop parsers/tools using this grammar.
 * In return, we ask that credit is given to us for developing this
 * grammar.  By "credit", we mean that if you incorporate our grammar or
 * the generated code into one of your programs (commercial product,
 * research project, or otherwise) that you acknowledge this fact in the
 * documentation, research report, etc....  In addition, you should say nice
 * things about us at every opportunity.
 *
 * As long as these guidelines are kept, we expect to continue enhancing
 * this grammar.  Feel free to send us enhancements, fixes, bug reports,
 * suggestions, or general words of encouragement at parrt@parr-research.com.
 * 
 * NeXT Computer Inc.
 * 900 Chesapeake Dr.
 * Redwood City, CA 94555
 * 12/02/1994
 * 
 * Restructured for public consumption by Terence Parr late February, 1995.
 *
 * DISCLAIMER: we make no guarantees that this grammar works, makes sense,
 *             or can be used to do anything useful.
 */
/* 2001-2002
 * Version 1.0
 * This C++ grammar file has been converted from PCCTS to run under 
 *  ANTLR to generate lexer and parser in C++ code by
 *  Jianguo Zuo and David Wigg at
 *  The Centre for Systems and Software Engineering
 *  London South Bank University
 *  London, UK.
 *
 */
/* 2003
 * Version 2.0 was published by David Wigg in September 2003
 */
/* 2004
 * Version 3.0 July 2004
 * This is version 3.0 of the C++ grammar definition for ANTLR to 
 *  generate lexer and parser in C++ code updated by
 *  David Wigg at
 *  The Centre for Systems and Software Engineering
 *  London South Bank University
 *  London, UK.
 */
/* 2005
 * Version 3.1 November 2005
 * Updated by David Wigg at London South Bank University
 *
 */
/* 2007
 * Version 3.2 November 2007
 * Updated by David Wigg at London South Bank University
 *
 * wiggjd@bcs.ac.uk
 * blackse@lsbu.ac.uk
 *
 * See MyReadMe.txt for further information
 *
 * This file is best viewed in courier font with tabs set to 4 spaces
 */
 


/* -- 2010 --
 * Version 4.0.1 August 2010
 * Modified and reworked to compile with ANTLR 3.2
 *  by Ramin Zaghi
 * 
 * Please note that this is the first public release
 *  for ANTLR 3.2; This does not comiple with any older
 *  versions of ANTLR. This may also have some missing 
 *  features compared to the 2007 update by David Wigg.
 *  I am publishing this work only to make this first
 *  ANTLR 3.2 update  available  to  the  community
 *  however if you are interested in a more complete 
 *  work please take a look at David's 2007 update.
 * 
 *  I emphasize that this new update needs more work
 *  and can be restructured to make it more developer
 *  friendly. The project file is a MSVS2008 project
 *  file and it only includes a "Debug" configuration.
 *  
 *  You may send your comments to < antlr3_cpp_parser@taggedprogramming.com >
 *  
 */





#pragma once
#ifndef _MEMBERS_FILE_
#define _MEMBERS_FILE_


#include "Helper/CPPSymbol.hpp"

#include    "CPP_grammar_Lexer.h"
#include    "CPP_grammar_Parser.h"

/******************************************************************/
extern pANTLR3_UINT8      fName;
extern pANTLR3_INPUT_STREAM       input;
extern pCPP_grammar_Lexer             lxr;
extern pANTLR3_COMMON_TOKEN_STREAM        tstream;
extern pCPP_grammar_Parser                psr;
CPPDictionary *symbols;
/******************************************************************/

boolean dummyBool = FALSE;
boolean dummyVar = FALSE;
boolean wasInTemplate = FALSE;

// File generated from CPP_parser.g
// Version 3.2 November 2007
// This file is best viewed in courier font with tabs set to 4 spaces
//
//	The statements in this block appear only in CPPParser.cpp

int tabs = 0; // added by V3-Author, counting local scopes

int statementTrace = 4;	// Used to control selected (level) tracing (see support.cpp)
						// 1 Shows which external and member statements selected
						// 2 Shows above plus all declarations/definitions
						// 3 reserved for future use
						// 4 and above available for user


	// Symbol table management stuff
	//CPPDictionary *symbols;
	int templateParameterScope;
	int externalScope;
	int anyType;
	int anyNonType;

	boolean _td;			// For typedef
	boolean _fd;			// For friend
	StorageClass _sc;	// For storage class
	TypeQualifier _tq;	// For type qualifier
	TypeSpecifier _ts;	// For type specifier
	FunctionSpecifier _fs;	// For declaration specifier
		
	int functionDefinition;	// 0 = Function definition not being parsed
							// 1 = Parsing function name
							// 2 = Parsing function parameter list
							// 3 = Parsing function block

	char qualifierPrefix[1024+1];//CPPParser_MaxQualifiedItemSize+1];
	char *enclosingClass;
	int assign_stmt_RHS_found;
	boolean in_parameter_list;
	boolean K_and_R;	// used to distinguish old K & R parameter definitions
	boolean in_return;
	boolean is_address;
	boolean is_pointer;

 	boolean antlrTracing;


void CPPParser__init()
{
	antlrTrace(TRUE);	// This is a dynamic trace facility for use with -traceParser etc.
						// It requires modification in LLkParser.cpp and LLkParser.hpp
						//  (Copies of these modified files are supplied with this code)
						//  otherwise it should be commented out (see MyReadMe.txt)
						// TRUE shows antlr trace (or can be set and reset during parsing)
						// FALSE stops showing antlr trace 
						// Provided the parser is always generated with -traceParser this
						//  facility allows trace output to be turned on or off just by changing
						//  the setting here from FALSE to TRUE or vice versa and then
						//  recompiling and linking CPPParser only thus avoiding the need
						//  to use antlr.Tool to re-generate the lexer and parser again
						//  with (or without) -traceParser each time before recompiling. 
						// Antlr trace can also be turned on and off dynamically using
						//  antlrTrace_on or antlrTrace_off statements inserted into the
						//  source code being parsed (See antlrTrace_on and antlrTrace_off below).

	// Creates a dictionary to hold symbols with 4001 buckets, 200 scopes and 800,000 characters
	// These can be changed to suit the size of program(s) being parsed
	symbols = new CPPDictionary(4001, 200, 800000);

	// Set template parameter scope - Not used at present
	templateParameterScope = symbols->getCurrentScopeIndex();	// Set template parameter scope to 0

	symbols->saveScope();	// Advance currentScope from 0 to 1
	// Set "external" scope for all types
	externalScope = symbols->getCurrentScopeIndex();	// Set "external" scope to 1 for types

	// Declare predefined scope "std" in external scope
	CPPSymbol *a = new CPPSymbol("std", CPPSymbol::otTypedef);
	symbols->define("std", a);

	symbols->saveScope();	// Advance currentScope from 1 to 2 (and higher) for all other symbols
							//  treated as locals

	// Global flags to allow for nested declarations
	_td = FALSE;		// For typedef
	_fd = FALSE;		// For friend
	_sc = scInvalid;	// For StorageClass
	_tq = tqInvalid;	// For TypeQualifier
	_ts = tsInvalid;	// For TypeSpecifier
	_fs = fsInvalid;	// For FunctionSpecifier

	functionDefinition = 0;
	qualifierPrefix[0] = '\0';
	enclosingClass = "";
	assign_stmt_RHS_found = 0;
	in_parameter_list = FALSE;
	K_and_R = FALSE;	// used to distinguish old K & R parameter definitions
	in_return = FALSE;
	is_address = FALSE;
	is_pointer = FALSE;
}









// Possibility of global stuff in the lexer cpp file
int deferredLineCount = 0;	// Used to accumulate line numbers in comments etc.

boolean in_user_file_deferred = FALSE;	// used to record first detection of user file


char principal_file[128];	// Path and name of user file set on reading the first preprocessor #line directive
int principal_line = 0;		// principal file's line number
int principal_last_set = 0; // where principal file's line number was last set

char current_included_file[128];	// Path and name of current include file
int include_line = 0; // include file's line number
int include_last_set = 0; // where included file's line number was last set


void deferredNewline() 
	{
	deferredLineCount++;	// Declared and initialised in main.cpp (Not TRUE!)
	}


// for processing #line .... lines (see note above)
void process_line_directive(const char *includedFile, const char *includedLineNo)
{
	// See global interface variables above
	// Working variables
	static int line, result;
	static boolean principal_file_set = FALSE;
	static int x;
	// Extract included file line no.
	result = sscanf(includedLineNo, "%d \n", &line);

	//printf("CPPLexer line directive on line %d\n",lineNo);
	// remove first " from file path+name by shifting all characters left
	for(x=1;includedFile[x]!='"';x++)
		{
		current_included_file[x-1] = includedFile[x];
		}

	// Check path and name are not too long
	if(x>128)
		{
		//
		printf("Path and name of included file too long\n");
		printf("Increase length of current_included_file and\n");
		printf("  principal_file to at least %d characters\n",x);
		printf("Abandon run\n");
		getchar();		    
		}

	// Replace last " from file name with null
	current_included_file[x-1] = NULL;

	// This will occur on reading the first preprocessor #line directive
	if (!principal_file_set)
		{
		strcpy (principal_file, current_included_file);
		principal_file_set = TRUE;
		}

	// check for main file name
	if (strcmp(principal_file, current_included_file) == 0)
		{
		principal_line = line;	// this is line no. shown in line directive
		principal_last_set = lxr->pLexer->getLine(lxr->pLexer); // CharScanner::getLine();	// This is line no. in preprocessed *.i file
		strcpy(current_included_file, " "); // delete include file name
		in_user_file_deferred = TRUE; // Users's .C or .CPP file (aka principal_file) detected
		}
	else
		// Check that this is a genuine path
		if(current_included_file[1]==':')
			{//printf("main.cpp 222 entered\n");
			//printf("main.cpp 223 %s %s\n",principal_file,current_included_file);
			include_line = line;	// this is line no. shown in line directive
			include_last_set = lxr->pLexer->getLine(lxr->pLexer);//CharScanner::getLine();	// This is line no. in preprocessed *.i file
			in_user_file_deferred = FALSE; // Header file file detected
			}
}


void antlrTrace(boolean traceFlag)
{
	antlrTracing = traceFlag;
}

void tab()
{
}

/*
int include_line;
boolean in_user_file_deferred;
int principal_last_set;
int principal_line;
char principal_file[128];
char current_included_file[128];

*/
int lineNo=0;
/*
void declaratorID(pANTLR3_UINT8 _s, QualifiedItem qi)
{

	int ii;
	char oth[25];
	memset(oth, 0, 25);
	const char* s = (char*)_s;

if (qi==qiInvalid     ) strcpy(oth, "qiInvalid");
if (qi==qiType        ) strcpy(oth, "qiType");
if (qi==qiDtor        ) strcpy(oth, "qiDtor");
if (qi==qiCtor        ) strcpy(oth, "qiCtor");
if (qi==qiOperator    ) strcpy(oth, "qiOperator");
if (qi==qiPtrMember   ) strcpy(oth, "qiPtrMember");
if (qi==qiVar         ) strcpy(oth, "qiVar");
if (qi==qiFun         ) strcpy(oth, "qiFun");

	for(ii=0;ii<tabs;ii++) printf(">");
	printf("%s: %s\n", s, oth);
}
*/



/*
 * PUBLIC DOMAIN PCCTS-BASED C++ GRAMMAR (cplusplus.g, stat.g, expr.g)
 *
 * Authors: Sumana Srinivasan, NeXT Inc.;            sumana_srinivasan@next.com
 *          Terence Parr, Parr Research Corporation; parrt@parr-research.com
 *          Russell Quong, Purdue University;        quong@ecn.purdue.edu
 *
 * VERSION 1.1
 *
 * SOFTWARE RIGHTS
 *
 * This file is a part of the ANTLR-based C++ grammar and is free
 * software.  We do not reserve any LEGAL rights to its use or
 * distribution, but you may NOT claim ownership or authorship of this
 * grammar or support code.  An individual or company may otherwise do
 * whatever they wish with the grammar distributed herewith including the
 * incorporation of the grammar or the output generated by ANTLR into
 * commerical software.  You may redistribute in source or binary form
 * without payment of royalties to us as long as this header remains
 * in all source distributions.
 *
 * We encourage users to develop parsers/tools using this grammar.
 * In return, we ask that credit is given to us for developing this
 * grammar.  By "credit", we mean that if you incorporate our grammar or
 * the generated code into one of your programs (commercial product,
 * research project, or otherwise) that you acknowledge this fact in the
 * documentation, research report, etc....  In addition, you should say nice
 * things about us at every opportunity.
 *
 * As long as these guidelines are kept, we expect to continue enhancing
 * this grammar.  Feel free to send us enhancements, fixes, bug reports,
 * suggestions, or general words of encouragement at parrt@parr-research.com.
 * 
 * NeXT Computer Inc.
 * 900 Chesapeake Dr.
 * Redwood City, CA 94555
 * 12/02/1994
 * 
 * Restructured for public consumption by Terence Parr late February, 1995.
 *
 * DISCLAIMER: we make no guarantees that this grammar works, makes sense,
 *             or can be used to do anything useful.
 */
/*
 * 2001-2003 Version 2.0 September 2003
 *
 * Some modifications were made to this file to support a project by
 * Jianguo Zuo and David Wigg at
 * The Centre for Systems and Software Engineering
 * South Bank University
 * London, UK.
 * wiggjd@bcs.ac.uk
 * blackse@lsbu.ac.uk
 *
 * These C++ functions are required to support the correct functioning of
 *	the CPP_parser.g definition of the C++ language.
*/
/* 2003-2004 Version 3.0 July 2004
 * Modified by David Wigg at London South Bank University for CPP_parser.g
 */
/* 2004-2005 Version 3.1 November 2005
 * Modified by David Wigg at London South Bank University for CPP_parser.g
 */
/* 2005-2007 Version 3.2 November 2007
 * Modified by David Wigg at London South Bank University for CPP_parser.g
 *
 * See MyReadMe.txt for further information
 *
 * This file is best viewed in courier font with tabs set to 4 spaces
 */

#include <iostream>
//#include "CPPParser.hpp"

extern int statementTrace;	// Used to control selected tracing at statement level
							//	for testing and program verification purposes

// Shorthand for a string of (qualifiedItemIs()==xxx||...)
int /*CPPParser__*/qualifiedItemIsOneOf(QualifiedItem qiFlags,   // Ored combination of flags
					int lookahead_offset)
	{	
	QualifiedItem qi = qualifiedItemIs(lookahead_offset); 
	return (qi & qiFlags) != 0; 
	}

// This is an important function, but will be replaced with
// an enhanced predicate in the future, once predicates
// and/or predicate guards can contain loops.
//
// Scan past the ::T::B:: to see what lies beyond.
// Return qiType if the qualified item can pose as type name.
// Note that T::T is NOT a type; it is a constructor.  Also,
// class T { ... T...} yields the enclosed T as a ctor.  This
// is probably a type as I separate out the constructor defs/decls,
// I want it consistent with T::T.
//
// In the below examples, I use A,B,T and example types, and
// a,b as example ids.
// In the below examples, any A or B may be a
// qualified template, i.e.,  A<...>
//
// T::T outside of class T yields qiCtor.
// T<...>::T outside of class T yields qiCtor.
// T inside of class T {...} yields qiCtor.
// T, ::T, A::T outside of class T yields qiType.
// a, ::a,  A::B::a yields qiId
// a::b yields qiInvalid
// ::operator, operator, A::B::operator yield qiOPerator
// A::*, A::B::* yield qiPtrMember
// ::*, * yields qiInvalid
// ::~T, ~T, A::~T yield qiDtor
// ~a, ~A::a, A::~T::, ~T:: yield qiInvalid

//xx //V3-Author
//#define SCOPE 53
//#define ID 9

#if !defined (cxt)
#define ctx psr 
#endif

/*CPPParser__*/QualifiedItem 
/*CPPParser__*/qualifiedItemIs(int lookahead_offset)
	{
	int k = lookahead_offset + 1;
	int final_type_idx = 0;
	// Skip leading "::"
	if (LT(k)->getType(LT(k)) == SCOPE)
		{k++;}
	// Skip sequences of T:: or T<...>::
	// DW 11/02/05 Note that LT(k)->getType() is not a "type" but a type of token, eg. ID, See STDCTokenTypes.hpp
	//firstIsTypeName((LT(k)->getText(LT(k)))->chars);
	printf("support.cpp qualifiedItemIs while reached k %d %s token %d isType %d, isClass %d\n",
		k,(LT(k)->getText(LT(k)))->chars,
//		LT(k)->getType()),	// DW Line replaced by one below 30/10/10
		LT(k)->getType(LT(k)),
		isTypeName((char*)(LT(k)->getText(LT(k)))->chars),
		isClassName((char*)(LT(k)->getText(LT(k)))->chars));
	while (LT(k)->getType(LT(k)) == ID && isTypeName((char*)(LT(k)->getText(LT(k)))->chars))
		{// If this type is the same as the last type, then ctor
		if (final_type_idx != 0 && 
			strcmp((char*)(LT(final_type_idx)->getText(LT(final_type_idx)))->chars, (char*)(LT(k)->getText(LT(k)))->chars) == 0)
			{// Like T::T
			// As an extra check, do not allow T::T::
			if (LT(k+1)->getType(LT(k+1)) == SCOPE)
				{//printf("support.cpp qualifiedItemIs qiInvalid returned\n");
				return qiInvalid;
				} 
			else 
				{//printf("support.cpp qualifiedItemIs qiCtor_1 returned %s %s %s \n",
				 //enclosingClass,(LT(lookahead_offset+1)->getText(LT(lookahead_offset+1)))->chars,
				 //(LT(final_type_idx)->getText(LT(final_type_idx)))->chars);
				return qiCtor;
				}
			}

		// Record this as the most recent type seen in the series
		final_type_idx = k;
		
		// Skip this token
		k++;

		// Skip over any template qualifiers <...>
		// I believe that "T<..." cannot be anything valid but a template
		if (LT(k)->getType(LT(k)) == LESSTHAN)
			{
			if (!skipTemplateQualifiers(k))
				{//printf("support.cpp qualifiedItemIs qiInvalid_2 returned\n");
				return qiInvalid;}
			//printf("support.cpp qualifiedItemIs template skipped, k %d\n",k);
			// k has been updated to token following <...>
			}

		// Skip any "::" and keep going
		if (LT(k)->getType(LT(k)) == SCOPE)
			{k++;}
		// Otherwise series terminated -- last ID in the sequence was a type
		else 
			{
			// Return ctor if last type is in containing class
			// We already checked for T::T inside loop
			printf("support.cpp qualifiedItemIs qiCtor_2 entered %s %s %s\n",
				enclosingClass,(LT(lookahead_offset+1)->getText(LT(lookahead_offset+1)))->chars,
				(LT(final_type_idx)->getText(LT(final_type_idx)))->chars);
			if (strcmp(enclosingClass,(char*)(LT(final_type_idx)->getText(LT(final_type_idx)))->chars)==0) 
				{printf("support.cpp qualifiedItemIs qiCtor_2 returned\n");
				return qiCtor;
				} 
			else 
				{printf("support.cpp qualifiedItemIs qiType_1 returned\n");
				return qiType;
				}
			}
		}

	// LT(k) is not an ID, or it is an ID but not a typename.
	//printf("support.cpp qualifiedItemIs second switch reached with type %d\n",LT(k)->getType(LT(k)));
	switch (LT(k)->getType(LT(k)))
		{
		case ID:
			// ID but not a typename
			// Do not allow id::
			if (LT(k+1)->getType(LT(k+1)) == SCOPE)
				{
				//printf("support.cpp qualifiedItemIs qiInvalid_3 returned\n");
				return qiInvalid;
				}
			if (strcmp(enclosingClass,(char*)(LT(k)->getText(LT(k)))->chars)==0 ) 
				{// Like class T  T()
				//printf("support.cpp qualifiedItemIs qiCtor_3 returned %s\n",enclosingClass);
				return qiCtor;
				}
			else 
				{
				if (isTypeName((char*)(LT(k)->getText(LT(k)))->chars))
					{
					//printf("support.cpp qualifiedItemIs qiType_2 returned\n");
					return qiType;
					}
	            else 			
					{
					//printf("support.cpp qualifiedItemIs qiVar returned\n");
					return qiVar;	// DW 19/03/04 was qiVar Could be function, qiFun?
					}
				}
		case TILDE:
			// check for dtor
			if (LT(k+1)->getType(LT(k+1)) == ID && 
				isTypeName((char*)(LT(k+1)->getText(LT(k+1)))->chars) &&
				LT(k+2)->getType(LT(k+2)) != SCOPE)
				{// Like ~B or A::B::~B
				 // Also (incorrectly?) matches ::~A.
				//printf("support.cpp qualifiedItemIs qiDtor returned\n");
				return qiDtor;
				} 
			else 
				{// ~a or ~A::a is qiInvalid
				//printf("support.cpp qualifiedItemIs qiInvalid_4 returned\n");
				return qiInvalid;
				}
			break;
		case STAR:
			// Like A::*
			// Do not allow * or ::*
			if (final_type_idx == 0)
				{// Haven't seen a type yet
				//printf("support.cpp qualifiedItemIs qiInvalid_5 returned\n");
				return qiInvalid;
				} 
			else 
				{//printf("support.cpp qualifiedItemIs qiPtrMember returned\n");
				return qiPtrMember;}
		case OPERATOR:
			// Like A::operator, ::operator, or operator
			//printf("support.cpp qualifiedItemIs qiOperator returned\n");
			return qiOperator;
		default:
			// Something that neither starts with :: or ID, or
			// a :: not followed by ID, operator, ~, or *
			//printf("support.cpp qualifiedItemIs qiInvalid_6 returned\n");
			return qiInvalid;
		}
	}

// Skip over <...>.  This correctly handles nested <> and (), e.g:
//    <T>
//    < (i>3) >
//    < T2<...> >
// but not
//    < i>3 >
//
// On input, kInOut is the index of the "<"
// On output, if the return is true, then 
//                kInOut is the index of the token after ">"
//            else
//                kInOut is unchanged
int /*CPPParser__*/skipTemplateQualifiers(int& kInOut)
	{// Start after "<"
	int k = kInOut + 1;

	while (LT(k)->getType(LT(k)) != GREATERTHAN) // scan to end of <...>
		{
		switch (LT(k)->getType(LT(k)))
			{
			case EOF:
				return 0;
			case LESSTHAN:
				if (!skipTemplateQualifiers(k))
					{return 0;}
				break;
			case LPAREN:
				if (!skipNestedParens(k))
					{return 0;}
				break;
			default:
				k++;     // skip everything else
				break;
			}
		if (k > MaxTemplateTokenScan)
			{return 0;}
		}

	// Update output argument to point past ">"
	kInOut = k + 1;
	return 1;
	}

// Skip over (...).  This correctly handles nested (), e.g:
//    (i>3, (i>5))
//
// On input, kInOut is the index of the "("
// On output, if the return is true, then 
//                kInOut is the index of the token after ")"
//            else
//                kInOut is unchanged
int /*CPPParser__*/skipNestedParens(int& kInOut)
	{// Start after "("
	int k = kInOut + 1;

	while (LT(k)->getType(LT(k)) != RPAREN)   // scan to end of (...)
		{
		switch (LT(k)->getType(LT(k)))
			{
			case EOF:
				return 0;
			case LPAREN:
				if (!skipNestedParens(k))
					{return 0;}
				break;
			default:
				k++;     // skip everything else
				break;
			}
		if (k > MaxTemplateTokenScan)
			{return 0;}
		}

	// Update output argument to point past ")"
	kInOut = k+1;
	return 1;
	}

// This was only used in scope_override but has now been replaced by a 
//   proper syntactic predicate
// DW 21/06/06 I think this can now be replaced by !finalqualifier(k) below
// Return true if "blah::" or "fu::bar<args>::..." found.
int /*CPPParser__*/scopedItem(int k)
	{
	printf("support.cpp scopedItem k %d\n",k);
	printf("support.cpp type %d finalQualifier %d\n",ID,!finalQualifier(k));
	printf("support.cpp return %d \n",(LT(k)->getType(LT(k))==ID && !finalQualifier(k)));
	return (LT(k)->getType(LT(k))==ID && !finalQualifier(k));
//	return (LT(k)->getType(LT(k))==SCOPE ||
//			(LT(k)->getType(LT(k))==ID && !finalQualifier(k)));
	}

// This was only used by scopedItem() above which is now not used (See above)
// Return true if ID<...> or ID is last item in qualified item list.
// Return false if LT(k) is not an ID.
// ID must be a type to check for ID<...>,
// or else we would get confused by "i<3"
int /*CPPParser__*/finalQualifier(int k)
	{
	if (LT(k)->getType(LT(k))==ID)
		{
		if (isTypeName((char*)(LT(k)->getText(LT(k)))->chars) && LT(k+1)->getType(LT(k+1))==LESSTHAN)
			{// Starts with "T<".  Skip <...>
			k++;
			skipTemplateQualifiers(k);
			} 
		else 
			{// skip ID;
			k++;
			}
		return (LT(k)->getType(LT(k)) != SCOPE );
		} 
	else 
		{// not an ID
		return 0;
		}
	}

/*
 * Return true if 's' can pose as a type name
 */
int /*CPPParser__*/isTypeName(const char *s)
	{
	//printf("isTypeName entered with %s\n",s);
	// To look for any type name only
	CPPSymbol *cs = (CPPSymbol *) symbols->lookup(s,CPPSymbol::otTypename);

	if (cs==NULL)
		{
		//printf("support.cpp isTypeName %s not found in dictionary\n",s);
		return 0;
		}

	// This should now be redundant
	if (cs->getType()==CPPSymbol::otTypedef||
		cs->getType()==CPPSymbol::otEnum||
		cs->getType()==CPPSymbol::otClass||
		cs->getType()==CPPSymbol::otStruct||
		cs->getType()==CPPSymbol::otUnion)
		{
		return 1;
		}
	else
		{// Warning to detect any failure of above 07/06/06
		printf("Support isTypeName warning symbol %s not type name\n",s);
		}

	return 0;
	}

/*
 * Return true if the most recently added matching entry 's' can pose as a type name
 */

int /*CPPParser__*/firstIsTypeName(const char *s)
	{
	CPPSymbol *cs = (CPPSymbol *) symbols->lookup(s,CPPSymbol::otInvalid);	// otInvalid is zero
	
	if (cs==NULL)
		{
		//printf("support.cpp isTypeName %s not found in dictionary\n",s);
		return 0;
		}

	//printf("support firstIsClassName this-scope %d\n",cs->this_scope);

	if (cs->getType()==CPPSymbol::otTypedef||
		cs->getType()==CPPSymbol::otEnum||
		cs->getType()==CPPSymbol::otClass||
		cs->getType()==CPPSymbol::otStruct||
		cs->getType()==CPPSymbol::otUnion)
		{
		return 1;
		}

	return 0;
	}


/*
 * Return true if 's' is a class name (or a struct which is a class
 * with all members public).
 */
int /*CPPParser__*/isClassName(const char *s)
	{
	// To look for any type name omly
	CPPSymbol *cs = (CPPSymbol *) symbols->lookup(s,CPPSymbol::otTypename);
	
	if ( cs==NULL ) return 0;
	
	if (cs->getType()==CPPSymbol::otClass||
		cs->getType()==CPPSymbol::otStruct||
		cs->getType()==CPPSymbol::otUnion) 
		{
		return 1;
		}

	return 0;
	}

void /*CPPParser__*/beginDeclaration()
	{
	}

void /*CPPParser__*/endDeclaration()
	{
	}

void /*CPPParser__*/beginFunctionDefinition()
	{
	functionDefinition = 1;
	}

void /*CPPParser__*/endFunctionDefinition()
	{
	// Remove parameter scope
	symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
	//printf("endFunctionDefinition remove parameter scope(%d):\n",symbols->getCurrentScopeIndex());
	symbols->removeScope();		// Remove symbols stored in current scope
	symbols->restoreScope();	// Reduce currentScope (higher level)
	//printf("endFunctionDefinition restoreScope() now %d\n",symbols->getCurrentScopeIndex());
	functionDefinition = 0;
	}

void /*CPPParser__*/beginConstructorDefinition()
	{functionDefinition = 1;}

void /*CPPParser__*/endConstructorDefinition()
	{
	symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
	symbols->removeScope();		// Remove symbols stored in current scope
	symbols->restoreScope();	// Reduce currentScope (higher level)
	//printf("endConstructorDefinition restoreScope() now %d\n",symbols->getCurrentScopeIndex());
	functionDefinition = 0;
	}

void /*CPPParser__*/beginConstructorDeclaration(const char *ctor)
	{ }

void /*CPPParser__*/endConstructorDeclaration()
	{ }

void /*CPPParser__*/beginDestructorDefinition()
	{functionDefinition = 1;}

void /*CPPParser__*/endDestructorDefinition()
	{
	symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
	symbols->removeScope();		// Remove symbols stored in current scope
	symbols->restoreScope();	// Reduce currentScope (higher level)
	//printf("endDestructorDefinition restoreScope() now %d\n",symbols->getCurrentScopeIndex());
	functionDefinition = 0;
	}

void /*CPPParser__*/beginDestructorDeclaration(const char *dtor)
	{ }

void /*CPPParser__*/endDestructorDeclaration()
	{ }

void /*CPPParser__*/beginParameterDeclaration()
	{ }

void /*CPPParser__*/beginFieldDeclaration()
	{ }

void /*CPPParser__*/declarationSpecifier(boolean td, boolean fd, StorageClass sc, TypeQualifier tq,
			 TypeSpecifier ts, FunctionSpecifier fs)
	{
	//printf("support.cpp declarationSpecifier td %d, fd %d, sc %d, tq %d, ts %d, fs %d\n",
	//	td,fd,sc,tq,ts,fs);
	_td = td;	// For typedef
	_fd = fd;	// For friend
	_sc = sc;
	_tq = tq;
	_ts = ts;
	_fs = fs;
	}

/* Symbols from declarators are added to the symbol table here. 
 * The symbol is also added to external scope or whatever the current scope is, in the symbol table. 
 * See list of object types below.
 */
//void /*CPPParser__*/declaratorID(const char *id,QualifiedItem qi)
void /*CPPParser__*/declaratorID(pANTLR3_UINT8/*char const **/ _id,QualifiedItem qi)
	{
	const char* id = (char*)_id;
	printf("Support.cpp declaratorID entered for %s at ptr %d, type %d\n",id,id,qi);
	//printf("Support.cpp declaratorID %d %s found, _ts = %d, _td = %d, qi = %d \n",
	//      lineNo,id,_ts,_td,qi);
	CPPSymbol *c = NULL;

	// if already in symbol table as a class, don't add
	// of course, this is incorrect as you can rename
	// classes by entering a new scope, but our limited
	// example basically keeps all types globally visible.
	if (symbols->lookup(id,CPPSymbol::otTypename)!=NULL)
		{
		// DW 21/11/10 A symbol may be used as non type as well as type so when found
		// in the symbol table we need to check whether the qualified item code is 
		// compatible with the object type of the stored symbol or not. If incompatible 
		// then we need to save it in the table as a new symbol within its current scope.
		CPPSymbol *c = (CPPSymbol *) symbols->lookup(id,CPPSymbol::otTypename);
		if (statementTrace >= 2)
			printf("%d support.cpp declaratorID %s (%d == %d) already stored in dictionary, ObjectType %d (%d)\n",
				lineNo,id,qi,qiType,c->getType(),isTypeName(id));
		// DW 21/11/10 Check if the new symbol is a type as well
		// If so, we do not need to store the new symbol in the symbols table
		if (qi==qiType)
			return;
		}

	if (qi==qiType)	// Check for type declaration
		{
		c = new CPPSymbol(id, CPPSymbol::otTypedef);
		//printf("Support.cpp declaratorID00 id %s\n",id);
		if (c==NULL) panic("can't alloc CPPSymbol");
		symbols->defineInScope(id, c, externalScope);
		//printf("Support.cpp declaratorID01 id %s\n",id);
		if(statementTrace >= 2)
			{
			printf("%d support.cpp declaratorID declare %s in external scope 1, ObjectType %d\n",
				lineNo,id,c->getType());
			}
		//printf("Support.cpp declaratorID03 id %s\n",id);
		// DW 04/08/03 Scoping not fully implemented
		// Typedefs all recorded in 'external' scope and therefor never removed
		}
	else if (qi==qiFun)	// Check for function declaration
		{
		//printf("Support.cpp declaratorID02 id %d id %s\n",id,id);
		c = new CPPSymbol(id, CPPSymbol::otFunction);
		if (c==NULL) panic("can't alloc CPPSymbol");
		symbols->define(id, c);	// Add to current scope
		//printf("Support.cpp declaratorID04 id %d id %s\n",id,id);
		if(statementTrace >= 2)
			{
			printf("%d support.cpp declaratorID declare %s in current scope %d, ObjectType %d\n",
				lineNo,id,symbols->getCurrentScopeIndex(),c->getType());
			}
		}
	else	   
		{
		if (qi!=qiVar)
			fprintf(stderr,"%d support.cpp declaratorID warning qi (%d) not qiVar (%d) for %s\n",
				lineNo,qi,qiVar,id); 

		c = new CPPSymbol(id, CPPSymbol::otVariable);
		if (c==NULL) panic("can't alloc CPPSymbol");
		symbols->define(id, c);	// Add to current scope
		if (statementTrace >= 2)
			printf("%d support.cpp declaratorID declare %s in current scope %d, ObjectType %d\n",
				lineNo,id,symbols->getCurrentScopeIndex(),c->getType());
		}
	}
/* These are the object types
	0 = otInvalid
	1 = otFunction
	2 = otVariable
	3 = otTypedef	Note. 3-7 are type names
	4 = otStruct	Note. 4, 5 & 7 are class names
	5 = otUnion
	6 = otEnum
	7 = otClass
   10 = otTypename
   11 = otNonTypename
*/

void /*CPPParser__*/declaratorID(char const * _id, QualifiedItem qi)
{
    declaratorID(reinterpret_cast<pANTLR3_UINT8>(const_cast<char*>(_id)), qi);
}

void /*CPPParser__*/declaratorArray()
	{ }

void /*CPPParser__*/declaratorParameterList(int def)
	{
	symbols->saveScope();	// Advance currentScope (lower level)
	//printf("declaratorParameterList saveScope() now %d\n",symbols->getCurrentScopeIndex());
	}

void /*CPPParser__*/declaratorEndParameterList(int def)
	{
	if (!def)
		{
		symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
		symbols->removeScope();		// Remove symbols stored in current scope
		symbols->restoreScope();	// Reduce currentScope (higher level)
		//printf("declaratorEndParameterList restoreScope() now %d\n",symbols->getCurrentScopeIndex());
		}
	}

void /*CPPParser__*/functionParameterList()
	{
	symbols->saveScope();	// Advance currentScope (lower level)
	//printf("functionParameterList saveScope() now %d\n",symbols->getCurrentScopeIndex());
	// DW 25/3/97 change flag from function to parameter list
	// DW 07/03/07 Taken out because it caused a problem when function declared within function and
	//               it was not actually used anywhere. (See in_parameter_list)
	//functionDefinition = 2;
	}

void /*CPPParser__*/functionEndParameterList(int def)
	{
	// If this parameter list is not in a definition then this
	if ( !def)
		{
		symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
		symbols->removeScope();		// Remove symbols stored in current scope
		symbols->restoreScope();	// Reduce currentScope (higher level)
		//printf("functionEndParameterList restoreScope() now %d\n",symbols->getCurrentScopeIndex());
		}
	else
		{
		// Change flag from parameter list to body of definition
		functionDefinition = 3;
		}
	// Otherwise endFunctionDefinition removes the parameters from scope
	}

void /*CPPParser__*/enterNewLocalScope()
	{
	symbols->saveScope();	// Advance currentScope (lower level)
	//printf("enterNewLocalScope saveScope() now %d\n",symbols->getCurrentScopeIndex());
	}

void /*CPPParser__*/exitLocalScope()
	{
	symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
	symbols->removeScope();		// Remove symbols stored in current scope
	symbols->restoreScope();	// Reduce currentScope (higher level)
	//printf("exitLocalScope restoreScope() now %d\n",symbols->getCurrentScopeIndex());
	}

void /*CPPParser__*/enterExternalScope()
	{// Scope has been initialised to 1 in CPPParser.init() in CPPParser.hpp
	functionDefinition = 0;
	}

void /*CPPParser__*/exitExternalScope()
	{
	symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
	symbols->removeScope();		// Remove symbols stored in current scope s/b 2
	symbols->restoreScope();	// Reduce currentScope (higher level)

	symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
	symbols->removeScope();		// Remove symbols stored in current scope s/b 1
	symbols->restoreScope();	// Reduce currentScope (higher level)

	if (symbols->getCurrentScopeIndex()==0)
		fprintf(stdout,"\nSupport exitExternalScope, scope now %d as required\n",symbols->getCurrentScopeIndex());
	else
		fprintf(stderr,"\nSupport exitExternalScope, scope now %d, should be 0\n",symbols->getCurrentScopeIndex());
	}

void /*CPPParser__*/classForwardDeclaration(const char *tag, TypeSpecifier ts, FunctionSpecifier fs)
	{
	CPPSymbol *c = NULL;

	// if already in symbol table as a class, don't add
	// of course, this is incorrect as you can rename
	// classes by entering a new scope, but our limited
	// example basically keeps all types globally visible.
	if (symbols->lookup(tag,CPPSymbol::otTypename)!=NULL)
		{
		CPPSymbol *cs = (CPPSymbol *) symbols->lookup(tag,CPPSymbol::otTypename);
		if (statementTrace >= 2)
			printf("%d support.cpp classForwardDeclaration %s already stored in dictionary, ObjectType %d\n",
				lineNo,tag,cs->getType());
		return;
		}

	switch (ts)
		{
		case tsSTRUCT :
			c = new CPPSymbol(tag, CPPSymbol::otStruct);
			break;
		case tsUNION :
			c = new CPPSymbol(tag, CPPSymbol::otUnion);
			break;
		case tsCLASS :
			c = new CPPSymbol(tag, CPPSymbol::otClass);
			break;
		}

	if ( c==NULL ) panic("can't alloc CPPSymbol");

	symbols->defineInScope(tag, c, externalScope);
	if (statementTrace >= 2)
		printf("%d support.cpp classForwardDeclaration declare %s in external scope, ObjectType %d\n",
			lineNo,tag,c->getType());

	// If it's a friend class forward decl, put in global scope also.
	// DW 04/07/03 No need if already in external scope. See above.
	//if ( ds==dsFRIEND )
	//	{
	//	CPPSymbol *ext_c = new CPPSymbol(tag, CPPSymbol::otClass);
	//	if ( ext_c==NULL ) panic("can't alloc CPPSymbol");
	//	if ( symbols->getCurrentScopeIndex()!=externalScope )	// DW 04/07/03 Not sure this test is really necessary
	//		{
	//		printf("classForwardDeclaration defineInScope(externalScope)\n");
	//		symbols->defineInScope(tag, ext_c, externalScope);
	//		}
	//	}

	}

void /*CPPParser__*/beginClassDefinition(const char *tag, TypeSpecifier ts)
	{
	CPPSymbol *c;
		if (statementTrace >= 2)	// DW 28/11/10
			printf("%d support.cpp beginClassDefinition entered tag %s qualifierPrefix %s\n",
				lineNo,tag,qualifierPrefix);

	// if already in symbol table as a class, don't add
	// of course, this is incorrect as you can rename
	// classes by entering a new scope, but our limited
	// example basically keeps all types globally visible.
	if (symbols->lookup(tag,CPPSymbol::otTypename) != NULL)
		{
		symbols->saveScope();   // still have to use scope to collect members
		//printf("support.cpp beginClassDefinition_1 saveScope() now %d\n",symbols->getCurrentScopeIndex());
		if (statementTrace >= 2)
			printf("%d support.cpp beginClassDefinition classname %s already in dictionary\n",
				lineNo,tag);
		return;
		}

	switch (ts)
		{
		case tsSTRUCT:
			c = new CPPSymbol(tag, CPPSymbol::otStruct);
			break;
		case tsUNION:
			c = new CPPSymbol(tag, CPPSymbol::otUnion);
			break;
		case tsCLASS:
			c = new CPPSymbol(tag, CPPSymbol::otClass);
			break;
		}
	if (c==NULL) panic("can't alloc CPPSymbol");

	symbols->defineInScope(tag, c, externalScope);	// Adds tag to dictionary in external scope

	if (statementTrace >= 2)
		printf("%d support.cpp beginClassDefinition define %s in external scope (1), ObjectType %d\n",
			lineNo,tag,c->getType());

	strcat(qualifierPrefix, tag);
	strcat(qualifierPrefix, "::");

	// add all member type symbols into the global scope (not correct, but
	// will work for most code).
	// This symbol lives until the end of the file
	symbols->saveScope();   // Advance currentScope (lower level)
	}

void /*CPPParser__*/endClassDefinition()
	{
	symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
	symbols->removeScope();		// Remove symbols stored in current scope
	symbols->restoreScope();	// Reduce currentScope (higher level)
	// remove final T:: from A::B::C::T::
	// upon backing out of last class, qualifierPrefix is set to ""
	char *p = &(qualifierPrefix[strlen(qualifierPrefix)-3]);
	while ( p > &(qualifierPrefix[0]) && *p!=':' ) 
		{p--;}
	if ( p > &(qualifierPrefix[0]) ) 
		p++;
	*p = '\0';
	}

void /*CPPParser__*/enumElement(const char *e)
	{ 
	CPPSymbol *c = new CPPSymbol(e, CPPSymbol::otVariable);
	if (c==NULL) panic("can't alloc CPPSymbol");
	symbols->define(e, c);	// Add to current scope
	if(statementTrace >= 2)
		printf("%d support.cpp declaratorID declare %s in current scope %d, ObjectType %d\n",
			lineNo,e,symbols->getCurrentScopeIndex(),c->getType());
	}

void /*CPPParser__*/beginEnumDefinition(const char *e)
	{// DW 26/3/97 Set flag for new class
	
	// add all enum tags into the global scope (not correct, but
	// will work for most code).
	// This symbol lives until the end of the file
	CPPSymbol *c = new CPPSymbol(e, CPPSymbol::otEnum);
	if (c==NULL) panic("can't alloc CPPSymbol");
	symbols->defineInScope(e, c, externalScope);
	if (statementTrace >= 2)
		printf("%d support.cpp beginEnumDefinition %s define in external scope, ObjectType %d\n",
			lineNo,e,c->getType());
	}

void /*CPPParser__*/endEnumDefinition()
	{	
	}

void /*CPPParser__*/templateTypeParameter(const char *t)
	{
	//DW 11/06/03 Symbol saved in templateParameterScope (0)
	//  as a temporary measure until scope is implemented fully
	// This symbol lives until the end of the file
	CPPSymbol *e = new CPPSymbol(t, CPPSymbol::otTypedef);	// DW 22/03/05
//	CPPSymbol *e = new CPPSymbol(t, CPPSymbol::otClass);
	if (e==NULL) panic("can't alloc CPPSymbol");
//	symbols->defineInScope(t, e, templateParameterScope);	// DW 22/03/05
	// DW 10/08/05 Replaced to make template parameters local
	symbols->defineInScope(t, e, externalScope);
//	symbols->define(t,e);	// Save template parameter in local scope
	if (statementTrace >= 2)
//		printf("%d support.cpp templateTypeParameter declare %s in  parameter scope (0), ObjectType %d\n",
		printf("%d support.cpp templateTypeParameter declare %s in  external scope (1), ObjectType %d\n",
			lineNo,t,e->getType());
//		printf("%d support.cpp templateTypeParameter declare %s in current scope %d, ObjectType %d\n",
//			lineNo,t,symbols->getCurrentScopeIndex(),e->getType());
	}

void /*CPPParser__*/beginTemplateDeclaration()
	{
	symbols->saveScope();	// Advance currentScope (lower level)
	//printf("Support beginTemplateDeclaration, Scope now %d\n",symbols->getCurrentScopeIndex());
	}

void /*CPPParser__*/endTemplateDeclaration()
	{
	symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
	symbols->removeScope();		// Remove symbols stored in current scope
	symbols->restoreScope();	// Reduce currentScope (higher level)
	//printf("Support endTemplateDeclaration, Scope now %d\n",symbols->getCurrentScopeIndex());
	}

void /*CPPParser__*/beginTemplateDefinition()
	{
	}

void /*CPPParser__*/endTemplateDefinition()
	{
	}

void /*CPPParser__*/beginTemplateParameterList()
	{ 
	// DW 26/05/03 To scope template parameters
	symbols->saveScope();	// Advance currentScope (lower level)
	}

void /*CPPParser__*/endTemplateParameterList()
	{ 
	// DW 26/05/03 To end scope template parameters
	symbols->restoreScope();	// Reduce currentScope (higher level)
	}

void /*CPPParser__*/exceptionBeginHandler()
	{ }

void /*CPPParser__*/exceptionEndHandler()
	{// remove parm elements from the handler scope
	symbols->dumpScope(stdout);	// Diagnostic - See CPPDictionary.hpp
	symbols->removeScope();		// Remove symbols stored in current scope
	symbols->restoreScope();	// Reduce currentScope (higher level)
	}

void /*CPPParser__*/end_of_stmt()
	{
#ifdef MYCODE
	myCode_end_of_stmt();
#endif MYCODE
	}                    

void /*CPPParser__*/panic(const char *err)
	{
	fprintf(stdout, "CPPParser: %s\n", err);
	exit(-1);
	}

//	Functions which may be overridden by MyCode subclass

void /*CPPParser__*/myCode_pre_processing(int argc,char *argv[])
	{
	}

void /*CPPParser__*/myCode_post_processing()
	{
	}

void /*CPPParser__*/myCode_end_of_stmt()
	{
	}

void /*CPPParser__*/myCode_function_direct_declarator(const char *id)
	{
	//printf("support myCode_function_direct_declarator entered for %s\n",id);
	}


#endif


